/**
 * @overview Cesium 公共方法封装
 * @author dengqiang
 * @update  2021.12.06
 */

class cesiumMapTool {
  constructor(viewer) {
    this.viewer = viewer
  }

  /**
   * @description 添加3D图片
   * @param option 几何体条件选项
   * @param geoType 实体的几何类型
   * @param that 传递 使用当前方法的 对象，调用 vuex方法
   */
  addImage3D(option) {
    const materialUtilImage = new CgsMaterialUtil()
    //材质对象
    let imageMaterialPropertyImage
    if (option.type === 'nbdl') {
      imageMaterialPropertyImage = materialUtilImage.createMaterialProperty('Image', {
        // image: require(`../../src/assets/img/Gansu/Huagong/roadWidth/${Math.floor(
        //   option.width
        // )}.png`),
      })
      //贴地矩形
      const optRect1Image = {
        positions: [
          [option.x - 0.00006, option.y - 0.00005],
          [option.x + 0.00006, option.y + 0.00005],
        ],
        name: '',
        rotation: 0,
        material: imageMaterialPropertyImage,
        materialState: true,
        outline: false,
        labelfont: '20px 宋体',
        height: option.z, //不要给高度，默认贴在地形上,
        zIndex: 1000,
      }
      const rectImage = new CgsRect(optRect1Image)
      map.addFeature(rectImage)
    } else {
      imageMaterialPropertyImage = materialUtilImage.createMaterialProperty('Image', {
        // image:require(`../../src/assets/images/roadWidth/${Math.floor(option.width)}.png`)
        // image: require(`../../src/assets/img/Gansu/Huagong/LimitHeight/${Math.floor(
        //   option.width
        // )}.png`),
      })
      const wallImage = new CgsWall({
        positions: [
          [option.x - 0.00003, option.y, option.z + 9],
          [option.x + 0.00003, option.y, option.z + 9],
        ],
        diffHeight: 6,
        fillColor: 'rgba(0, 0, 255, 0)',
        material: imageMaterialPropertyImage,
        materialState: true,
        outlineColor: 'rgba(0, 0, 0, 0)',
      })
      //添加
      map.addFeature(wallImage)
    }
  }

  /**
   * @description 添加3D文字
   * @param option 几何体条件选项
   * @param geoType 实体的几何类型
   * @param that 传递 使用当前方法的 对象，调用 vuex方法
   */
  addText3D(option) {
    const map = window.map
    const materialUtil1 = new CgsMaterialUtil()

    // 贴地文字******************************************
    const textMaterialProperty1 = materialUtil1.createMaterialProperty('Text', {
      text: option.text || '',
      font: '50px 楷体',
      fill: true,
      fillColor: Cesium.Color.DARKGREEN,
      stroke: true,
      strokeWidth: 3,
      strokeColor: Cesium.Color.WHITE,
      backgroundColor: new Cesium.Color(0.0, 0.0, 0.0, 0),
    })
    //根据传入的字符串长度，计算矩形。

    //贴地矩形
    const optRect = {
      positions: [
        // [118.795098,32.157894],
        // [118.795198,32.157994]
        [option.pos.x, option.pos.y],
        [option.pos.x + 0.00003 * option.text.length, option.pos.y + 0.0001],
      ],
      height: option.height,
      name: '',
      rotation: 0,
      material: textMaterialProperty1,
      materialState: true,
      outline: true,
      labelfont: '20px 宋体',
    }
    const rect = new CgsRect(optRect)
    map.addFeature(rect)
  }

  /**
   * @description 生成几何体
   * @param option 几何体条件选项
   * @param geoType 实体的几何类型
   * @param that 传递 使用当前方法的 对象，调用 vuex方法
   */
  addEntity(option, geoType, that) {
    let entity, newId, shape
    switch (geoType) {
      case 'billboard':
        if (option.pos.longitude < 0) {
          const cartesian3 = {}
          cartesian3.x = option.pos.longitude
          cartesian3.y = option.pos.latitude
          cartesian3.z = option.pos.height
          option.pos = this.car3ToWGS84(cartesian3)
        }
        const secondId = option.id + option.secondType
        entity = {
          position: [option.pos.longitude, option.pos.latitude, option.pos.height],
          url: option.imgUrl,
          id: secondId,
          name: option.name,
          scale: 0.5,
          // click: option.click || '',
          visibleHeight: [10, 85110],
          labelVisibleHeight: [10, 85110],
          // labelShow: false,
        }
        newId = `${option.secondType}_${option.id}`
        const marker = map3DControl.createImagePoint(entity)
        marker.type = option.secondType
        // marker.setVisible(option.visible  || true);
        // 采集系统默认为 true； 化工指挥默认为 false
        if (option.visible != undefined) {
          marker.setVisible(option.visible)
        } else {
          marker.setVisible(true)
        }
        if (that) {
          that.$store.state.overlaysMap.set(`#${newId}`, marker)
        }
        window.map3DControl.addFeature(
          option.name + '_' + (Math.random() * 10000000).toFixed(),
          marker
        )
        break
      case 'polygon':
        entity = {
          id: option.id || undefined,
          name: option.name || '',
          position: option.centerpos,
          label: {
            text: option.name || '',
            font: option.font || '18px san-serif',
            pixelOffset: new Cesium.Cartesian2(0, -10),
            // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 220),
            disableDepthTestDistance: 1270,
            // fillColor: new Cesium.Color(1, 1, 1, 1), //填充色
            showBackground: true, //是否显示背景
            backgroundColor: option.backgroundColor || new Cesium.Color(0.165, 0.165, 0.165, 0.8), //背景颜色
            backgroundPadding: option.backgroundPadding || new Cesium.Cartesian2(7, 5), //背景边距
            fillColor: option.fillColor || Color.WHITE, //填充色
            outlineColor: option.outlineColor || Color.BLACK, //外线颜色
            outlineWidth: option.outlineWidth || 1.0, //外线宽
          },
          polygon: {
            hierarchy: option.pos,
            material: option.color || Cesium.Color.BLUE.withAlpha(0.7),
            perPositionHeight: false,
            outline: true,
            outlineColor: Cesium.Color.BLUE.withAlpha(0.7),
            outlineWidth: 1.0,
            // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 1000)
            // extrudedHeight: 60
          },
        }
        shape = this.viewer.entities.add(entity)
        // shape.show = option.visible || true;
        // 采集系统默认为 true； 化工指挥默认为 false
        if (option.visible != undefined) {
          shape.show = option.visible
        } else {
          shape.show = true
        }
        shape.type = option.secondType
        newId = `${option.secondType}_${option.id}`
        if (that) {
          that.$store.state.overlaysMap.set(`#${newId}`, entity)
        }
        return shape
        break
      case 'wall':
        // 添加中心点标注
        if (option.centerpos != undefined) {
          const obj = {}
          obj.lng = option.centerpos.x
          obj.lat = option.centerpos.y
          obj.alt = option.centerpos.z + 20
          const newCenterPos = this.WGS84ToCar3(obj)
          entity = {
            id: option.id || undefined,
            name: option.name || '',
            position: newCenterPos,
            label: {
              text: option.name || '',
              font: '18px san-serif',
              pixelOffset: new Cesium.Cartesian2(0, -10),
              distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 6000),
              // disableDepthTestDistance: 1270,
              fillColor: new Cesium.Color(1, 1, 1, 1),
              showBackground: true,
              disableDepthTestDistance: 10000,
            },
          }
          window.map3DControl.viewer.entities.add(entity)
        }

        //添加墙体
        var array = []

        option.pos.forEach((ele) => {
          const e = []
          if (ele.x < 0) {
            //笛卡尔空间坐标系
            var cartographic = Cesium.Cartographic.fromCartesian(ele)
            e.push((cartographic.longitude * 180) / Math.PI)
            e.push((cartographic.latitude * 180) / Math.PI)
          } else {
            var cartographic = {
              height: ele.z,
              latitude: ele.y,
              longitude: ele.x,
            }
            e.push(cartographic.longitude)
            e.push(cartographic.latitude)
          }
          e.push(cartographic.height)
          //这里的墙体高度调用处传，或者写死
          // e.push(option.wallHeight || 1785);
          array.push(e)
        })

        var scrollWall = new CgsScrollWall({
          positions: array,
          style: {
            diffHeight: option.diffHeight || (option.secondType == 'cqbj' ? 50 : 16), //高度
            color: option.color || Cesium.Color.BLUE.withAlpha(0.7),
            // color: '#00ff00',
            speed: 10,
            reverse: false, //方向：true往上、false往下
          },
          show: true,
        })

        scrollWall.feature3D.type = option.secondType
        // scrollWall.feature3D.primitive.show = false;
        scrollWall.feature3D.primitive.show = option.visible

        window.map3DControl.addFeature(option.id, scrollWall)
        return scrollWall
        break
      default:
        break
    }
  }

  /**
   * 根据字段删除entity
   * @constructor
   */
  removeEntityBySecName(secondType) {
    window.map3DControl.viewer.entities.values.forEach((ele) => {
      if (ele.secondName.includes(secondType)) {
        window.map3DControl.viewer.entities.remove(ele)
      }
    })
  }

  /**
   * WGS84坐标系转笛卡尔坐标系
   * @param point
   * @return {{x: *, y: *, z: *}}
   * @constructor
   */
  WGS84ToCar3(cartographic) {
    const car3 = Cesium.Cartesian3.fromDegrees(cartographic.lng, cartographic.lat, cartographic.alt)
    const x = car3.x
    const y = car3.y
    const z = car3.z
    return { x: x, y: y, z: z }
  }

  /**
   * 笛卡尔空间坐标系转WGS84坐标系
   * @param cartesian3
   * @return {{longitude: *, latitude: *, height: *}}
   * @constructor
   */
  car3ToWGS84(cartesian3) {
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
    const lat = Cesium.Math.toDegrees(cartographic.latitude)
    const lng = Cesium.Math.toDegrees(cartographic.longitude)
    const alt = cartographic.height
    return { longitude: lng, latitude: lat, height: alt }
  }

  /**
   * 笛卡尔空间坐标系转WGS84坐标系
   * @param cartesian3
   * @return {{longitude: *, latitude: *, height: *}}
   * @constructor
   */
  car3ToWGS84Two(cartesian3) {
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
    const lat = Cesium.Math.toDegrees(cartographic.latitude)
    const lng = Cesium.Math.toDegrees(cartographic.longitude)
    const alt = cartographic.height
    return { lng: lng, lat: lat, alt: alt }
  }

  /**
   * 定时器修改透明度
   * @constructor
   */
  requestAnimationFrame(color, boolean, time, item) {
    cancelAnimationFrame(item.rafId) //先清除一次

    let x = 1
    let flog = true
    // let cloneColor = color.getValue().clone()
    // 记录初始透明度
    if (!item.oldAlpha) {
      item.oldAlpha = color._value.alpha
    }
    //当前执行时间
    let nowTime = 0
    //记录每次动画执行结束的时间
    let lastTime = Date.now()
    //我们自己定义的动画时间差值
    const diffTime = time

    if (boolean) {
      ;(function animloop() {
        //记录当前时间
        nowTime = Date.now()
        // 当前时间-上次执行时间如果大于diffTime，那么执行动画，并更新上次执行时间
        if (nowTime - lastTime > diffTime) {
          lastTime = nowTime
          if (flog) {
            x = Number((x - 0.1).toFixed(2))
            if (x <= 0.1) {
              flog = false
            }
          } else {
            x = Number((x + 0.1).toFixed(2))
            if (x >= 0.9) {
              flog = true
            }
          }
        }
        color._value.alpha = x
        item.rafId = requestAnimationFrame(animloop)
      })()
    } else {
      color._value.alpha = item.oldAlpha
      cancelAnimationFrame(item.rafId)

      delete item.oldAlpha
      delete item.rafId
    }
  }

  /**
   * 定时器修改透明度(无法通过属性直接修改)
   * @constructor
   */
  requestAnimationFrameTwo(color, boolean, time, item) {
    cancelAnimationFrame(item.rafId) //先清除一次

    let x = 1
    let flag = true
    const cloneColor = color.getValue().clone()
    // 记录初始透明度
    if (!item.oldAlpha) {
      item.oldAlpha = color._value.alpha
    }
    //当前执行时间
    let nowTime = 0
    //记录每次动画执行结束的时间
    let lastTime = Date.now()
    //我们自己定义的动画时间差值
    const diffTime = time

    if (boolean) {
      ;(function animloop() {
        //记录当前时间
        nowTime = Date.now()
        // 当前时间-上次执行时间如果大于diffTime，那么执行动画，并更新上次执行时间
        if (nowTime - lastTime > diffTime) {
          lastTime = nowTime
          if (flag) {
            x = Number((x - 0.1).toFixed(2))
            if (x <= 0.1) {
              flag = false
            }
          } else {
            x = Number((x + 0.1).toFixed(2))
            if (x >= 0.9) {
              flag = true
            }
          }
        }
        color.setValue(cloneColor.withAlpha(x))
        item.rafId = requestAnimationFrame(animloop)
      })()
    } else {
      color.setValue(cloneColor.withAlpha(item.oldAlpha)) //还原透明度
      cancelAnimationFrame(item.rafId) //清除定时器

      delete item.oldAlpha
      delete item.rafId
    }
  }

  /**
   * 返回JSON格式的坐标 进行转化
   * @param car
   * @return {{latitude, longitude, height}}
   */
  carToCarLabel(car) {
    return { longitude: car.x, latitude: car.y, height: car.z || car.height }
  }

  /**
   * 批量笛卡尔空间坐标系转WGS84坐标系
   * @param [cartesian3]
   */
  changeCoordinate(array) {
    const test = []
    array.forEach((ele) => {
      const wgs84 = car3ToWGS84(ele)
      test.push([wgs84.longitude, wgs84.latitude, wgs84.height])
    })
    console.log(test)
  }

  /**
   * 关闭所有的监听鼠标点击事件
   * @param null
   * @return null
   * @constructor
   */
  removeEventListener() {
    windiow.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    windiow.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
  }

  /**
   * 传入面点坐标集合，计算面的中心点
   * @param cartesian3List:[{x:,y:,z:},{x:,y:,z:},{x:,y:,z:}]
   * @return cartesian3
   */
  getPolygonCenter(cartesian3List) {
    let x = 0
    let y = 0
    let z = 0
    const length = cartesian3List.length
    cartesian3List.forEach((ele) => {
      const cartographic = this.car3ToWGS84(ele)

      x += cartographic.longitude
      y += cartographic.latitude
      z += cartographic.height
    })
    const cartesian3 = this.WGS84ToCar3({
      lng: x / length,
      lat: y / length,
      alt: z / length,
    })
    return cartesian3
  }

  /**
   * 传入面点坐标集合，计算面的中心点
   * @param cartesian3List:[{x:,y:,z:},{x:,y:,z:},{x:,y:,z:}]
   * @return cartesian3
   */
  getPolygonCenterTwo(pos) {
    let x = 0
    let y = 0
    let z = 0
    pos.forEach((item) => {
      x += item.lng
      y += item.lat
      z += item.alt
    })
    return { lng: x / pos.length, lat: y / pos.length, alt: z / pos.length }
  }

  /**
   * 加载单个动态的GIF标牌
   * @param option:
   * {
   *     point:  { lng: 118.828696, lat: 32.268877, height: 100 }, //点坐标
   *     id:   'skidjgksjdiksj'                                      //class类型（供删除用）
   * }
   * @return null
   */
  addGifBillboard(option) {
    const viewer = window.map3DControl.viewer
    const htmlOverlay = document.createElement('div')

    htmlOverlay.style.zIndex = 8888
    htmlOverlay.style.position = 'absolute'
    htmlOverlay.style.display = 'block'
    htmlOverlay.style.cursor = 'pointer'
    htmlOverlay.style.caretColor = 'rgba(0, 0, 0, 0)'

    const imgBase64 = require('/src/assets/images/common/fire.gif')
    const htmlStr =
      `<img id='` +
      option.id +
      `' src='` +
      imgBase64 +
      `' class='gifBillboard' style='width: 48px;height: 48px'>`
    htmlOverlay.innerHTML = htmlStr
    document.body.appendChild(htmlOverlay)

    const scratch = new Cesium.Cartesian2()
    viewer.scene.preRender.addEventListener(function () {
      const position = Cesium.Cartesian3.fromDegrees(
        option.point.lng,
        option.point.lat,
        option.point.height
      )
      const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(position, scratch)
      if (Cesium.defined(canvasPosition)) {
        htmlOverlay.style.top = canvasPosition.y - 48 + 'px'
        htmlOverlay.style.left = canvasPosition.x - 24 + 'px'
      }
    })
  }

  /**
   * 按照id删除动态GIF标牌
   * @param id:'skidjgksjdiksj'
   * @return null
   */
  removeGifBillboard(id) {
    document.getElementById(id).remove()
  }

  /**
   * 删除所有动态GIF标牌
   * @param null
   * @return null
   */
  removeAllGifBillboard() {
    const allGifBillboard = document.getElementsByClassName('gifBillboard')
    for (let i = 0; i < allGifBillboard.length; i++) {
      allGifBillboard[i].remove()
    }
  }

  /**
   * 加载单个 火焰粒子效果
   * @param config {Object}
   * {
   * }
   * @param that {Object}
   */
  addParticleEffect(config, that) {
    const newId = `${config.class}_${config.id}`

    //火灾粒子特效
    const options = {
      position: [config.point.lng, config.point.lat, config.point.height], // 喷泉位置坐标
      particles: [
        // 粒子对象，可使用多个粒子进行叠加
        {
          url: 'assets/image/particle/fire.png', // 粒子的纹理文件路径
          startColor: 'rgba(255.0,0.0,0.0,0.3)', // 粒子效果开始颜色
          endColor: 'rgba(255.0,255.0,0.0,0.7)', // 粒子效果结束颜色
          rate: 100, // 一次性产生的粒子数（增长率）
          startScale: 13.0, // 开始缩放比例
          endScale: 2.0, // 结束缩放比例
          rotation: [0.0, 100.0, 0.0], // 粒子自身旋转角度
          width: 20.0, // 粒子宽度
          height: 20.0, // 粒子高度
          minLife: 1,
          maxLife: 3,
          radius: 10,
          visibleDistance: [0.0, 5000.0], // 可视距离 m
        },
      ],
    }
    const explodeFeature = new CgsExplode(options)
    explodeFeature.setVisible(true)
    if (that) {
      that.$store.state.overlaysMap.set(`#${newId}`, explodeFeature)
    }
    window.map3DControl.addFeature(newId, explodeFeature)
  }

  /**
   * 移除火焰粒子效果标记
   * @param config {Object}
   * {
   *     class: 'fireParticle' 类型
   *     id: '' 唯一标识
   * }
   */
  removeParticleEffect(config) {
    const newId = `${config.class}_${config.id}`
    window.map3DControl.removeFeature(newId)
  }

  /**
   * 设置 受灾半径
   * @param {String} featureName 当前受灾对象 featur名称id
   * @param {Number} radius 半径
   */
  setParticleRadius(featureName, radius) {
    const explodeFeature = window.map3DControl.getFeature(featureName)
    // let radiusList = explodeFeature.feature.setRadius(-1);
    // console.log('所有粒子半径', radiusList)
    if (!explodeFeature) {
      return
    }
    explodeFeature.feature.setRadius(radius, -1)
  }

  /**
   * 获取空间中两点之间的直线距离（适合忽略地球自身曲率的两侧）
   * @param point1   经纬度以及高度对象  {lng:, lat:, height: }
   * @param point2   经纬度以及高度对象
   * @return eucDistance  欧式距离
   */
  measureDistance(pot1, pot2) {
    //获取两个点的经纬度坐标和高程
    const point1Car3 = Cesium.Cartographic.fromDegrees(pot1.lng, pot1.lat, pot1.alt)
    const point2Car3 = Cesium.Cartographic.fromDegrees(pot2.lng, pot2.lat, pot2.alt)
    //根据经纬度计算距离
    const geodesic = new Cesium.EllipsoidGeodesic()
    geodesic.setEndPoints(point1Car3, point2Car3)
    let distance = geodesic.surfaceDistance
    //返回两点之间的距离
    distance = Math.sqrt(Math.pow(distance, 2) + Math.pow(point1Car3.height - point2Car3.height, 2))
    return distance
  }

  /**
   * 多边形面积测量（适合小面积测量）
   * @param points   [{lng:, lat:, height:}]
   */
  measurePolygonArea() {
    const earthRadiusMeters = 6371000 //地球半径近似值
    const radiansPerDegree = Math.PI / 180
    const degreesPerRadian = 180 / Math.PI

    for (let i = 0; i < points.length - 2; i++) {
      const j = (i + 1) % points.length
      const k = (i + 1) % points.length
      const totalAngle = Angle(points[i], points[j], points[k])
      const dis_temp1 = getFlatternDistance(point[i], points[j])
      const dis_temp2 = getFlatternDistance(point[j], points[k])
      res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle))
    }
    return res.toFixed(2)

    //角度量测
    function Angle(p1, p2, p3) {
      const bearing21 = Bearing(p2, p1)
      const bearing23 = Bearing(p3, p2)
      let angle = bearing21 - bearing23
      if (angle < 0) {
        angle += 360
      }
      return angle
    }

    //方向量测
    function bearing(from, to) {
      const lat1 = from.lat * radiansPerDegree
      const lng1 = from.lon * radiansPerDegree
      const lat2 = to.lat * radiansPerDegree
      const lng2 = to.lon * radiansPerDegree
      let angle = -Math.atan2(
        Math.sin(lon1 - lon2) * Math.cos(lat2),
        Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
      )
      if (angle < 0) {
        angle += Math.PI * 2.0
      }
      angle = angle * degreesPerRadian
      return angle
    }
  }

  /**
   * 多边形面积测量（适合小面积测量）
   * @param points   [Cartesian3,Cartesian3,...]   笛卡尔空间坐标系
   */
  measureCar3Area(points) {
    let s = 0
    let p1 = 0
    let p2 = 0
    for (let i = 0; i < points.length; ++i) {
      p1 = points[i]
      const j = (i + 1) % points.length
      p2 = points[j]
      s += p1.x * p2.y
      s -= p2.x * p1.y
    }
    return JSON.parse(Math.abs(s).toFixed(8))
  }

  /**
   * 判断点是否在多边形内
   * @param polygonArray [{x:118, y:36},...]
   * @param testPoint {x:116, y:36}
   * @return
   */
  inPolygonOrNot(polygonArray, testPoint) {
    const xArr = []
    const yArr = []
    const testx = testPoint.x
    const testy = testPoint.y
    const pointNum = polygonArray.length
    polygonArray.forEach((ele) => {
      xArr.push(ele.x)
      yArr.push(ele.y)
    })

    let i = 0,
      j = 0,
      c = 0
    for (i = 0, j = pointNum - 1; i < pointNum; j = i++) {
      if (
        yArr[i] >= testy != yArr[j] >= testy &&
        testx <= ((xArr[j] - xArr[i]) * (testy - yArr[i])) / (yArr[j] - yArr[i]) + xArr[i]
      ) {
        c = !c
      }
    }
    return c == 0 ? false : true
  }

  /**
   * 3D map 上添加 模型标记
   * @param config
   */
  addModelLabel(config, that) {
    const newId = `${config.secondType}_${config.id}`
    const model = new CgsModel({
      name: '',
      position: [config.pos.longitude, config.pos.latitude, config.pos.height],
      // url: `./models/fire_hydrant/scene.gltf`,
      url: config.url,
      markUrl: config.img,
      // markUrl: `./models/fire_hydrant/textures/lambert1_normal.png`,
      scale: 1.0,
      rotation: [0, 0, 0],
      markRotation: 180,
      maximumScale: 25.0, // 最大尺寸(倍率)
      autoScale: false, // 自动缩放, 若为true, 地图缩放时模型的大小不发生变化, 若为false, 随着视角拉近, 模型会变大
      minimumPixelSize: 128, //  最小像素尺寸(像素)
    })
    // that.$store.state.overlaysMap.set(`#${newId}`, model);
    if (config.visible != undefined) {
      model.setVisible(config.visible)
    } else {
      model.setVisible(true)
    }
    if (that) {
      that.$store.state.overlaysMap.set(`#${newId}`, model)
    }
    window.map3DControl.addFeature(config.name + '_' + (Math.random() * 10000000).toFixed(), model)
  }

  /**
   * 计算B点相对A点所在方位，正北为零度。
   * @param pointA {lng:,lat:}
   * @param pointB {lng:,lat:}
   */
  calculateAngle(pointA, pointB) {
    const ditanceX = pointB.lng - pointA.lng
    const ditanceY = pointB.lat - pointA.lat
    const k = ditanceX / ditanceY
    const baseAngle = Math.atan(k)
    let finalAngle = 0
    if (ditanceX > 0 && ditanceY > 0) {
      //第一象限
      finalAngle = (baseAngle * 180) / Math.PI
    } else if (ditanceY < 0) {
      //第二、三象限
      finalAngle = ((baseAngle + Math.PI) * 180) / Math.PI
    } else {
      //第四象限
      finalAngle = ((baseAngle + 2 * Math.PI) * 180) / Math.PI
    }
    return finalAngle
  }

  /**
   * @description 漫游定位
   * @param option {pos：{lng:118, lat:23, height:1000}}
   */
  flyTo(option) {
    //默认视角
    const orientation = {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: Cesium.Math.toRadians(0),
    }
    this.viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(option.pos.lng, option.pos.lat, option.pos.height), //必填，目标点坐标
      duration: option.flyTime || 3, //非必填，漫游持续的时间
      // complete: option.callBack || function () { },//非必填，漫游结束时的回调函数
      orientation: option.orientation || orientation,
    })
  }

  /**
   * @description 将米转成对应经纬度数
   * @param option {length：10, latitude:33} length 单位：米, latitude用来确定纬线长度
   */
  trsfMeterToXY(option) {
    const earthPerimeter = 40030173 //地球赤道周长
    const result = {
      longitude: 0,
      latitude: 0,
    }
    const k = 1.42 //因地球为不规则椭圆，所以需要矫正
    result.longitude =
      ((option.length * 360) / earthPerimeter) *
      Math.cos(((option.latitude || 33) * Math.PI) / 180) *
      k //如不传，则使用江苏所在纬度
    result.latitude = (option.length * 360) / earthPerimeter
    return result
  }
}

export default cesiumMapTool
